"use strict";

var router = require("router"),
    TokenService = require("router").TokenService,
    mongo = require('./core/mongoservice'),
    ObjectId = require('mongodb').ObjectID,
    Q = require('q');

function AlertReportService() {
    console.log("AlertReportService constructor");
}
AlertReportService.prototype = Object.create(TokenService.prototype);
AlertReportService.prototype.constructor = AlertReportService;


AlertReportService.prototype.getFromShopToken = function (request, response, promise) {
    return promise.then(function (self) {
        self.identify(request, response);
        var shopId = request.payload.shop.id;
        return self.mongoGetByShopId(shopId).then(function (report) {
            return response.send({ request: request, content: report });
        });
    });
};

/*-------------------------------------------------------*/
/*mongo daf*/
AlertReportService.prototype.mongoGetByShopId = function (shopId) {
    if (!shopId) throw new Error("shopId is not defined.");
    var self = this;

    var query = {
        "shop.id": new ObjectId(shopId),
        "alert.dates.maturity": { "$gte": new Date() }
    };

    return mongo.find('alerts.reports', query).then(function (cursor) {
        return Q.ninvoke(cursor, 'toArray').then(function (reports) {
            reports.forEach(function (item) {
                item.reports = self.generateUserReports(item.reports); //replace reports
            })
            return reports;
        })
    });
};

AlertReportService.prototype.mongoInsert = function (alert) {
    if (!alert) throw new Error("alert is not defined.");
    var self = this;

    var doc = { 
        alert: { 
            id: alert._id,
            dates: alert.dates
        }, 
        shop: { id: alert.shop.id},
        reports: []
    }

    return mongo.insert('alerts.reports', doc).then(function (docs) {
        return docs[0];
    }).then(function (doc) {
        return self.mongoUpdate(alert);
    });
};

AlertReportService.prototype.mongoPullCurrentReport = function (alertId) {
    if (!alertId) throw new Error("alertId is not defined.");
    var self = this;

    var today = new Date();
    today.setHours(0, 0, 0, 0);
    var rp = { date: today };

    var report = {
        date: today,
        users: {
            near: [],
            subscribers: []
        }
    };

    return mongo.update('alerts.reports', { "alert.id": new ObjectId(alertId) }, { $pull: { "reports": rp} }, { multi: true }).then(function () {
        return report;
    });
};

AlertReportService.prototype.mongoPushCurrentReport = function (alertId, report) {
    if (!alertId) throw new Error("alertId is not defined.");
    if (!report) throw new Error("report is not defined.");

    return mongo.update('alerts.reports', { "alert.id": alertId }, { $push: { "reports": report} });
}

AlertReportService.prototype.mongoPushPreviousReport = function (alertId, currentReport) {
    if (!alertId) throw new Error("alertId is not defined.");
    if (!currentReport) throw new Error("currentReport is not defined.");

    var previousDate = new Date(currentReport.date);
    previousDate.setDate(previousDate.getDate() - 1);

    return mongo.findOne('alerts.reports', { "alert.id": new ObjectId(alertId), "reports.0.date": previousDate }).then(function (doc) {
        if (!doc) {
            return mongo.findOne('alerts.reports', { "alert.id": new ObjectId(alertId) }).then(function (doc) {
                if (doc && doc.reports.length > 0) {
                    var previousReport = doc.reports[0]; //on recopie le plus récent des rapports
                    previousReport.date = previousDate;
                    return mongo.update('alerts.reports', { "alert.id": alertId }, { $push: { "reports": previousReport} });
                }
            })
        }
    });
}

AlertReportService.prototype.mongoUpdate = function (alert) {
    if (!alert) throw new Error("alert is not defined.");
    var self = this;
    return self.mongoPullCurrentReport(alert._id).then(function (report) {
        report.users = alert.users;

        return self.mongoPushPreviousReport(alert._id, report).then(function () {
            return self.mongoPushCurrentReport(alert._id, report);
        });
    });
}

/*-------------------------------------------------------*/
/*common*/
AlertReportService.prototype.generateUserReport = function (report) {
    if (!report) throw new Error("report is not defined.");

    var usersNearTotal = report.users.near.length;
    var usersNearRead = report.users.near.filter(function (element) {
        return element.read != undefined;
    }).length;

    var usersSubscribersTotal = report.users.subscribers.length;
    var usersSubscribersRead = report.users.subscribers.filter(function (element) {
        return element.read != undefined;
    }).length;

    return {
        date: report.date,
        users: {
            near: {
                total: usersNearTotal,
                read: usersNearRead,
                unread: usersNearTotal - usersNearRead
            },
            subscribers: {
                total: usersSubscribersTotal,
                read: usersSubscribersRead,
                unread: usersSubscribersTotal - usersSubscribersRead
            }
        }
    };
};

AlertReportService.prototype.generateUserReports = function (reports) {
    if (!reports) throw new Error("reports is not defined.");
    var self = this;

    var userReports = [];
    reports.forEach(function (report) {
        userReports.push(self.generateUserReport(report));
    });
    return userReports;
};


exports = module.exports = new AlertReportService();